package com.example.gkcircle.widget;

import android.animation.ValueAnimator;
import android.content.Context;
import android.support.v4.view.MotionEventCompat;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Interpolator;
import android.widget.AbsListView;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.RelativeLayout;

import com.example.gkcircle.App;
import com.example.gkcircle.R;

/**
 * Created by Jehu on 16/4/10.
 * 下拉放大listView
 */
public class PullZoomListView extends ListView{

    //Header的容器
    private View mHeaderContainer;
    //Header的背景图
    private ImageView mHeaderImage;
    //Header宽度
    private int mHeaderWidth;
    //Header高度
    private int mHeaderHeight;
    //无效的点
    private static final int INVALID_POINTER = -1;
    //滑动动画执行的时间
    private static final int MIN_SETTLE_DURATION = 200;
    ///记录上一次手指触摸的点
    private float mLastMotionY;
    //当前活动的点Id,有效的点的Id
    protected int mActivePointerId = INVALID_POINTER;
    //放大的倍数
    private float mScale;
    //上一次放大的倍数
    private float mLastScale;
    //最大放大的倍数
    private final float mMaxScale = 3.0f;
    //是否需要禁止ListView 的事件响应
    private boolean isNeedCancelParent;
    private OnScrollListener mScrollListener;
    //下拉刷新的阈值
    private final float REFRESH_SCALE = 1.20F;
    //下拉刷新监听
    private OnRefreshListener mRefreshListener;
    private LayoutInflater inflater;
    private int startY;
    private boolean isRecored;
    private int firstItemIndex;


    public PullZoomListView(Context context) {
        super(context);
        init(context);
    }

    public PullZoomListView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public PullZoomListView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }

    private void init(Context context){
        inflater=LayoutInflater.from(context);
        mHeaderContainer=(RelativeLayout)inflater.inflate(R.layout.library_book_detail_header, null);
        mHeaderImage=(ImageView)mHeaderContainer.findViewById(R.id.library_book_detail_header_bg);
        mHeaderWidth= App.screenWidth;
        mHeaderHeight = (int) ((9 * 1.0f / 17) * mHeaderWidth);
        LayoutParams absLayoutParams = new LayoutParams(mHeaderWidth, mHeaderHeight);
        mHeaderContainer.setLayoutParams(absLayoutParams);
        RelativeLayout.LayoutParams imgLayoutParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT);
        mHeaderImage.setLayoutParams(imgLayoutParams);
        addHeaderView(mHeaderContainer);
        //设置监听事件
        super.setOnScrollListener(new InternalScrollerListener());
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        final int action = ev.getAction() & MotionEventCompat.ACTION_MASK;
        switch (action) {
            case MotionEvent.ACTION_DOWN:
                if (firstItemIndex == 0 && !isRecored) {
                    isRecored = true;
                    // 记录下down事件的y位置
                    startY = (int) ev.getY();
                }
                /* 计算 x，y 的距离 */
                int index = MotionEventCompat.getActionIndex(ev);
                mActivePointerId = MotionEventCompat.getPointerId(ev, index);
                if (mActivePointerId == INVALID_POINTER) break;
                mLastMotionY = MotionEventCompat.getY(ev, index);
                //计算算一次放缩的比例
                mLastScale = (this.mHeaderContainer.getBottom() / this.mHeaderHeight);
                //当按下的时候把这个标志为设为有效
                isNeedCancelParent = true;
                break;
            case MotionEvent.ACTION_MOVE:
                int tempY = (int) ev.getY();
                if (!isRecored && firstItemIndex == 0) {
                    isRecored = true;
                    startY = tempY;
                }
                int indexMove = MotionEventCompat.getActionIndex(ev);
                mActivePointerId = MotionEventCompat.getPointerId(ev, indexMove);

                if (mActivePointerId == INVALID_POINTER) {
				/* 这里相当于松手 */
                    finishPull();
                    isNeedCancelParent = true;
                    break;
                }else {
                /* 这是一个关键值，通过这个值来判断是否需要放大图片 */
                    if (mHeaderContainer.getBottom() >= mHeaderHeight) {
                        ViewGroup.LayoutParams params = this.mHeaderContainer.getLayoutParams();
                        final float y = MotionEventCompat.getY(ev, indexMove);
                        float dy = y - mLastMotionY;
                        float f = ((y - this.mLastMotionY + this.mHeaderContainer.getBottom()) / this.mHeaderHeight - this.mLastScale) / 2.0F + this.mLastScale;
                        if ((this.mLastScale <= 1.0D) && (f <= this.mLastScale)) {
                            params.height = this.mHeaderHeight;
                            this.mHeaderContainer.setLayoutParams(params);
                            return super.onTouchEvent(ev);
                        }
					/* 这里设置紧凑度 */
                        dy = dy * 0.5f * (mHeaderHeight * 1.0f / params.height);
                        mLastScale = (dy + params.height) * 1.0f / mHeaderHeight;
                        mScale = clamp(mLastScale, 1.0f, mMaxScale);
                        params.height = (int) (mHeaderHeight * mScale);
                        mHeaderContainer.setLayoutParams(params);
                        mLastMotionY = y;
					/* 这里，如果图片有放大，则屏蔽ListView 的其他事件响应 */
                        if (isNeedCancelParent) {
                            isNeedCancelParent = false;
                            MotionEvent motionEvent = MotionEvent.obtain(ev);
                            motionEvent.setAction(MotionEvent.ACTION_CANCEL);
                            super.onTouchEvent(motionEvent);
                        }
                        return true;
                    }
                    mLastMotionY = MotionEventCompat.getY(ev, indexMove);
                }
                break;
            case MotionEvent.ACTION_UP:
                isRecored = false;
                finishPull();
                break;
            case MotionEvent.ACTION_POINTER_UP:
                /*
			 * 这里需要注意，多点处理，这里的处理方式是：如果有两个手指按下，抬起的是后按下的手指，则不做处理
			 * 如果抬起的是最先按下的手指，则复原图片效果。
			 */
                int pointUpIndex = MotionEventCompat.getActionIndex(ev);
                int pointId = MotionEventCompat.getPointerId(ev, pointUpIndex);
                if (pointId == mActivePointerId) {
				/* 松手执行结束拖拽操作 */
				/* 结束事件响应，做相应的操作 */
                    finishPull();
                }
                break;
        }
        return super.onTouchEvent(ev);
    }

    //设置Header的背景图
    public void setmHeaderImageResource(int res) {
        this.mHeaderImage.setImageResource(res);
    }

    //提供获取Header容器的方法
    public View getmHeaderContainer() {
        return mHeaderContainer;
    }

    //下拉刷新接口
    public interface OnRefreshListener {
        void onRefresh();
    }
    //回调方法
    public void setOnRefreshListener(OnRefreshListener l) {
        mRefreshListener = l;
    }

    //定义了一个时间插值器，根据ViewPage控件来定义的
    private static final Interpolator sInterpolator = new Interpolator() {
        public float getInterpolation(float t) {
            t -= 1.0f;
            return t * t * t * t * t + 1.0f;
        }
    };


    private class InternalScrollerListener implements OnScrollListener {
        @Override
        public void onScrollStateChanged(AbsListView view, int scrollState) {
            if (mScrollListener != null) {
                mScrollListener.onScrollStateChanged(view, scrollState);
            }
        }

        @Override
        public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
            firstItemIndex = firstVisibleItem;
            float diff = mHeaderHeight - mHeaderContainer.getBottom();
            if ((diff > 0.0F) && (diff < mHeaderHeight)) {
                int i = (int) (0.3D * diff);
                mHeaderImage.scrollTo(0, -i);
            } else if (mHeaderImage.getScrollY() != 0) {
                mHeaderImage.scrollTo(0, 0);
            }
            if (mScrollListener != null) {
                mScrollListener.onScroll(view, firstVisibleItem, visibleItemCount, totalItemCount);
            }
        }
    }

    private void finishPull() {
        mActivePointerId = INVALID_POINTER;
        if (mHeaderContainer.getBottom() > mHeaderHeight) {
            pullBackAnimation();
        }
    }


    private void pullBackAnimation() {
        ValueAnimator pullBack = ValueAnimator.ofFloat(mScale, 1.0f);
        pullBack.setInterpolator(sInterpolator);
        pullBack.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float value = (Float) animation.getAnimatedValue();
                LayoutParams params = (LayoutParams) mHeaderContainer.getLayoutParams();
                params.height = (int) (mHeaderHeight * value);
                mHeaderContainer.setLayoutParams(params);
            }
        });
        pullBack.setDuration((long) (MIN_SETTLE_DURATION * mScale));
        pullBack.start();
    }

    private float clamp(float value, float min, float max) {
        return Math.min(Math.max(value, min), max);
    }

}
